/**
 * 钩子模块 给一个方法添加钩子，调用Hook.doActions执行方法上的所有钩子函数
 *
 * @author mrbian
 * @date 2016.8.19
 */

var Hook = (function (){
    var _initHook = function(method) {             // 每次修改hook的时候都需要调用，防止throw
        if(! method["__hook__"]){
            method["__hook__"] = {
                actions : [],
                filters : []
            };
        }
    };

    /**
     * 比较函数，保证优先值大的在数组的前面
     * @param hook1
     * @param hook2
     * @returns {number} 小于0 则hook1在hook2的前面
     * @private
     */
    var _compare = (hook1,hook2) => {       // sort默认排序是从1开始，从a开始，啊xiaoyu
        return hook2.priority - hook1.priority;
    };

    /**
     * 给一个方法添加钩子函数
     * @param method
     * @param action
     * @param priority
     */
    var addAction= function(method,action,priority) {
        _initHook(method);
        var actions = method["__hook__"].actions;
        actions.push({
            action : action,
            priority : priority || 10
        });
        actions.sort(_compare);
    };

    /**
     * 执行调用此函数的方法的所有钩子函数
     * @param args 非空则代替method的argument赋给钩子函数
     * @returns {boolean} 某一个action返回false，则全部返回false
     */
    var doActions = function(...args){
        var method = Hook.doActions.caller;
        _initHook(method);
        var actions = method["__hook__"].actions;
        if(args.length == 0){
            arguments = method.arguments;
        }
        for(var action of actions){
            if(action.action.apply(method,arguments) === false){
                return false;
            }
        }
    };

    /**
     * 某个方法是否具有某个钩子
     * @param method 方法
     * @param action 待查找的钩子函数
     * @returns {boolean} 非法或者没有返回false
     */
    var hasAction = function(method,action){
        _initHook(method);
        var actions = method["__hook__"].actions;
        if(action.length <= 0 || typeof(action) == "undefined" || action == null){
            return false;
        }
        for(var a of actions){
            if(a === action){
                return true;
            }
        }
        return false;
    };

    /**
     * 删除一个方法的所有或者某个钩子函数
     * @param method
     * @param [action] 可空，空则删除所有钩子
     */
    var removeAction = function(method,action){
        _initHook(method);
        var actions = method["__hook__"].actions;
        if(typeof(action) == "undefined"){          //如果第二个参数空，则直接清空
            method["__hook__"].actions = [];
            return;
        }
        if(hasAction(method,action)){               //如果方法有这个钩子
            method["__hook__"].actions.splice(actions.indexOf(action),1); //删除这个钩子
        }else{                                      //如果没有这个钩子
            throw "please make sure method has this action";    //要求程序员必须先确认存在这个钩子
        }
    };

    return {
        addAction,
        doActions,
        hasAction,
        removeAction
    }
}());

module.exports = Hook;